#region Header
//=============================================================================
//                          GShield (Game Shield)
//=============================================================================
//
// Original Programmer: Shawn Jackson
// Company: WaveTech Digital Technologies (www.wtdt.com)
// Copyright: (c) 2006 WaveTech Digital Technologies, Inc. All Rights Reserved.
// Assembly: Engine
// Code File Name: BannerFactory.cs
// Code File Date: 05/05/2007
//
// Code File Info: Banner Factory for UI Theming. Original Code from the KeePass
//                 Open Source Project by Dominik Reichl.
//=============================================================================
/*
 * UPDATES
 * -------
 *                ShawnJ 5/4/2007 (0.9.0.x): Refactoring for OSS.
 */
#endregion Header

#region License

/*
  GShield - Game Shield
  Copyright (C) 2006-2007 WaveTech Digital Technologies, Inc.
                                http://www.wtdt.com

  This program is free software; you can redistribute it and/or modify
  it under the terms of the GNU General Public License as published by
  the Free Software Foundation; either version 2 of the License, or
  (at your option) any later version.

  This program is distributed in the hope that it will be useful,
  but WITHOUT ANY WARRANTY; without even the implied warranty of
  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  GNU General Public License for more details.

  You should have received a copy of the GNU General Public License
  along with this program; if not, write to the Free Software
  Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
*/

#endregion License

#region Includes

using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Drawing;
using System.Drawing.Drawing2D;
using System.Drawing.Imaging;

#endregion

namespace WaveTech.GShield.Engine.Factories
{
	public static class BannerFactory
	{
		private const int MaxCachedImages = 32;
		private static readonly Dictionary<string, Image> m_vImageCache = new Dictionary<string, Image>();

		#region Banner Style

		public enum BannerStyle : uint
		{
			Default = 0,
			WinXPLogin,
			WinVistaBlack,
			KeePassWin32,
			BlueCarbon
		}

		#endregion Banner Style

		#region Create Banner

		/// <summary>
		/// Creates a Banner (Header Image) for application forms
		/// </summary>
		/// <param name="width">Width of the image</param>
		/// <param name="height">Height of the image</param>
		/// <param name="bs">Style of the Banner</param>
		/// <param name="icon">Icon image to use in the banner</param>
		/// <param name="title">Banner Title</param>
		/// <param name="line">Banner Information Line</param>
		/// <returns>Banner Image</returns>
		public static Image CreateBanner(int width, int height, BannerStyle bs, Image icon, string title, string line)
		{
			// icon may be null.
			Debug.Assert(title != null);
			if (title == null) throw new ArgumentNullException();
			Debug.Assert(line != null);
			if (line == null) throw new ArgumentNullException();

			string strImageID = width + "x" + height + ":";
			if (title != null) strImageID += title;
			strImageID += ":";
			if (line != null) strImageID += line;

			//if (bs == BannerStyle.Default)
			//  bs = (BannerStyle)AppConfigEx.GetUInt(AppDefs.ConfigKeys.BannerStyle);

			strImageID += ":" + ((uint) bs);

			// Try getting the banner from the banner cache.
			Image img;
			if (m_vImageCache.TryGetValue(strImageID, out img)) return img;

			// Banner not in cache already -> create new banner.
			img = new Bitmap(width, height, PixelFormat.Format24bppRgb);
			Graphics g = Graphics.FromImage(img);
			const int offsetIcon = 10;

			Color clrStart = Color.White;
			Color clrEnd = Color.LightBlue;
			float fAngle = 0.90f;

			if (bs == BannerStyle.BlueCarbon)
			{
				fAngle = 90.0f;

				clrStart = Color.LightGray;
				clrEnd = Color.Black;

				Rectangle rect = new Rectangle(0, 0, width, (height*3)/8);
				LinearGradientBrush washBrush = new LinearGradientBrush(rect, clrStart,
				                                                        clrEnd, fAngle, true);
				g.FillRectangle(washBrush, rect);

				clrStart = Color.FromArgb(0, 0, 32);
				clrEnd = Color.FromArgb(192, 192, 255);

				rect = new Rectangle(0, height/2, width, (height*5)/8);
				washBrush = new LinearGradientBrush(rect, clrStart,
				                                    clrEnd, fAngle, true);
				g.FillRectangle(washBrush, rect);
			}
			else
			{
				if (bs == BannerStyle.WinXPLogin)
				{
					clrStart = Color.FromArgb(200, 208, 248);
					clrEnd = Color.FromArgb(40, 64, 216);
				}
				else if (bs == BannerStyle.WinVistaBlack)
				{
					clrStart = Color.FromArgb(151, 154, 173);
					clrEnd = Color.FromArgb(27, 27, 37);

					fAngle = 90.0f;
				}
				else if (bs == BannerStyle.KeePassWin32)
				{
					clrStart = Color.FromArgb(235, 235, 255);
					clrEnd = Color.FromArgb(192, 192, 255);
				}

				Rectangle rect = new Rectangle(0, 0, width, height);
				LinearGradientBrush washBrush = new LinearGradientBrush(rect, clrStart,
				                                                        clrEnd, fAngle, true);
				g.FillRectangle(washBrush, rect);
			}

			if (icon != null)
			{
				int yIcon = (height - icon.Height)/2;
				g.DrawImageUnscaled(icon, offsetIcon, yIcon);

				ColorMatrix cm = new ColorMatrix();
				cm.Matrix33 = 0.1f;
				ImageAttributes ia = new ImageAttributes();
				ia.SetColorMatrix(cm);

				int w = icon.Width*3, h = icon.Height*3;
				int x = width - w - 10, y = (height - h)/2;
				Rectangle rectDest = new Rectangle(x, y, w, h);
				g.DrawImage(icon, rectDest, 0, 0, icon.Width, icon.Height,
				            GraphicsUnit.Pixel, ia);
			}

			if ((bs == BannerStyle.WinXPLogin) || (bs == BannerStyle.WinVistaBlack) || (bs == BannerStyle.BlueCarbon))
			{
				Rectangle rect = new Rectangle(0, height - 2, 0, 2);

				rect.Width = width/2 + 1;
				rect.X = width/2;
				clrStart = Color.FromArgb(248, 136, 24);
				clrEnd = Color.White;
				LinearGradientBrush brushOrangeWhite = new LinearGradientBrush(rect, clrStart, clrEnd, 0.90f, true);
				g.FillRectangle(brushOrangeWhite, rect);

				rect.Width = width/2 + 1;
				rect.X = 0;
				clrStart = Color.White;
				clrEnd = Color.FromArgb(248, 136, 24);
				LinearGradientBrush brushWhiteOrange = new LinearGradientBrush(rect, clrStart, clrEnd, 0.90f, true);
				g.FillRectangle(brushWhiteOrange, rect);
			}
			else if (bs == BannerStyle.KeePassWin32)
			{
				// Black separator line
				Pen penBlack = new Pen(Color.Black);
				g.DrawLine(penBlack, 0, height - 1, width - 1, height - 1);
			}

			Font font = new Font(FontFamily.GenericSansSerif, 12, FontStyle.Bold);

			Brush brush;
			if (bs == BannerStyle.KeePassWin32) brush = Brushes.Black;
			else brush = Brushes.White;

			float fx = 2*offsetIcon, fy = 9.0f;
			if (icon != null) fx += icon.Width;
			g.DrawString(title, font, brush, fx, fy);

			Font fontSmall = new Font(FontFamily.GenericSansSerif, 9, FontStyle.Regular);
			fx += offsetIcon;
			fy += offsetIcon*2 + 2;
			g.DrawString(line, fontSmall, brush, fx, fy);

			if (m_vImageCache.Count >= MaxCachedImages)
			{
				foreach (string strKey in m_vImageCache.Keys)
				{
					m_vImageCache.Remove(strKey);
					break;
				}
			}

			// Save in cache.
			m_vImageCache[strImageID] = img;

			return img;
		}

		#endregion Create Banner
	}
}